# -*- coding: utf-8 -*-
"""
文本显示区域组件
实现多行文本显示、自动滚动、颜色区分等功能
"""

import pygame
from typing import List, Tuple, Optional
from gui.components.base_component import BaseComponent
from gui.styles.colors import get_theme_color
from gui.styles.fonts import get_font


class TextArea(BaseComponent):
    """文本显示区域组件
    
    支持多行文本显示、自动滚动、颜色区分、滚动条等功能
    """
    
    def __init__(self, x: int, y: int, width: int, height: int):
        super().__init__(x, y, width, height)
        
        # 文本内容
        self.lines: List[Tuple[str, str]] = []  # (text, color_type)
        self.max_lines = 1000  # 最大行数限制
        
        # 滚动相关
        self.scroll_y = 0
        self.line_height = 20
        self.visible_lines = height // self.line_height
        
        # 滚动条相关
        self.show_scrollbar = True
        self.scrollbar_width = 12
        self.scrollbar_color = get_theme_color('scrollbar')
        self.scrollbar_handle_color = get_theme_color('scrollbar_handle')
        
        # 文本样式
        self.font = get_font('body')
        self.padding = 8
        self.text_colors = {
            'info': get_theme_color('text'),
            'warning': get_theme_color('warning'),
            'error': get_theme_color('error'),
            'success': get_theme_color('success')
        }
        
        # 背景色
        self.background_color = get_theme_color('input_bg')
        self.border_color = get_theme_color('border')
        
        # 自动滚动
        self.auto_scroll = True
        
        # 鼠标滚动
        self.scroll_speed = 3
        
    def add_line(self, text: str, color_type: str = 'info'):
        """添加一行文本
        
        Args:
            text: 文本内容
            color_type: 颜色类型 ('info', 'warning', 'error', 'success')
        """
        # 处理换行符
        lines = text.split('\n')
        for line in lines:
            # 处理长文本换行
            wrapped_lines = self._wrap_text(line)
            for wrapped_line in wrapped_lines:
                self.lines.append((wrapped_line, color_type))
        
        # 限制最大行数
        if len(self.lines) > self.max_lines:
            self.lines = self.lines[-self.max_lines:]
        
        # 自动滚动到底部
        if self.auto_scroll:
            self.scroll_to_bottom()
    
    def _wrap_text(self, text: str) -> List[str]:
        """文本换行处理"""
        if not text:
            return ['']
        
        # 计算可用宽度
        available_width = self.width - 2 * self.padding
        if self.show_scrollbar:
            available_width -= self.scrollbar_width
        
        # 简单的字符换行（可以优化为更智能的单词换行）
        lines = []
        words = text.split(' ')
        current_line = ''
        
        for word in words:
            test_line = current_line + (' ' if current_line else '') + word
            text_width = self.font.get_size(test_line)[0]
            
            if text_width <= available_width:
                current_line = test_line
            else:
                if current_line:
                    lines.append(current_line)
                    current_line = word
                else:
                    # 单个词太长，强制换行
                    lines.append(word)
        
        if current_line:
            lines.append(current_line)
        
        return lines if lines else ['']
    
    def clear(self):
        """清空所有文本"""
        self.lines.clear()
        self.scroll_y = 0
    
    def scroll_to_bottom(self):
        """滚动到底部"""
        max_scroll = max(0, len(self.lines) - self.visible_lines)
        self.scroll_y = max_scroll
    
    def scroll_to_top(self):
        """滚动到顶部"""
        self.scroll_y = 0
    
    def scroll_by(self, delta: int):
        """相对滚动
        
        Args:
            delta: 滚动行数，正数向下，负数向上
        """
        max_scroll = max(0, len(self.lines) - self.visible_lines)
        self.scroll_y = max(0, min(max_scroll, self.scroll_y + delta))
    
    def handle_event(self, event: pygame.event.Event) -> bool:
        """处理事件"""
        if not self.visible or not self.enabled:
            return False
        
        if event.type == pygame.MOUSEBUTTONDOWN:
            if self.rect.collidepoint(event.pos):
                # 鼠标滚轮滚动
                if event.button == 4:  # 向上滚动
                    self.scroll_by(-self.scroll_speed)
                    return True
                elif event.button == 5:  # 向下滚动
                    self.scroll_by(self.scroll_speed)
                    return True
                
                # 点击滚动条
                if self.show_scrollbar and self._is_scrollbar_click(event.pos):
                    self._handle_scrollbar_click(event.pos)
                    return True
        
        elif event.type == pygame.KEYDOWN:
            if self.focused:
                # 键盘滚动
                if event.key == pygame.K_UP:
                    self.scroll_by(-1)
                    return True
                elif event.key == pygame.K_DOWN:
                    self.scroll_by(1)
                    return True
                elif event.key == pygame.K_PAGEUP:
                    self.scroll_by(-self.visible_lines)
                    return True
                elif event.key == pygame.K_PAGEDOWN:
                    self.scroll_by(self.visible_lines)
                    return True
                elif event.key == pygame.K_HOME:
                    self.scroll_to_top()
                    return True
                elif event.key == pygame.K_END:
                    self.scroll_to_bottom()
                    return True
        
        return False
    
    def _is_scrollbar_click(self, pos: Tuple[int, int]) -> bool:
        """检查是否点击了滚动条"""
        if not self.show_scrollbar or len(self.lines) <= self.visible_lines:
            return False
        
        scrollbar_x = self.x + self.width - self.scrollbar_width
        return (scrollbar_x <= pos[0] <= self.x + self.width and
                self.y <= pos[1] <= self.y + self.height)
    
    def _handle_scrollbar_click(self, pos: Tuple[int, int]):
        """处理滚动条点击"""
        if len(self.lines) <= self.visible_lines:
            return
        
        # 计算点击位置对应的滚动位置
        relative_y = pos[1] - self.y
        scroll_ratio = relative_y / self.height
        max_scroll = len(self.lines) - self.visible_lines
        self.scroll_y = int(scroll_ratio * max_scroll)
        self.scroll_y = max(0, min(max_scroll, self.scroll_y))
    
    def update(self, dt: float):
        """更新组件状态"""
        pass
    
    def draw(self, surface: pygame.Surface):
        """绘制组件"""
        if not self.visible:
            return
        
        # 绘制背景
        pygame.draw.rect(surface, self.background_color, self.rect)
        pygame.draw.rect(surface, self.border_color, self.rect, 1)
        
        # 绘制文本
        self._draw_text(surface)
        
        # 绘制滚动条
        if self.show_scrollbar and len(self.lines) > self.visible_lines:
            self._draw_scrollbar(surface)
    
    def _draw_text(self, surface: pygame.Surface):
        """绘制文本内容"""
        if not self.lines:
            return
        
        # 计算文本区域
        text_x = self.x + self.padding
        text_y = self.y + self.padding
        text_width = self.width - 2 * self.padding
        if self.show_scrollbar and len(self.lines) > self.visible_lines:
            text_width -= self.scrollbar_width
        
        # 创建文本区域的裁剪矩形
        text_rect = pygame.Rect(text_x, text_y, text_width, self.height - 2 * self.padding)
        surface.set_clip(text_rect)
        
        # 绘制可见的文本行
        start_line = max(0, self.scroll_y)
        end_line = min(len(self.lines), start_line + self.visible_lines)
        
        for i in range(start_line, end_line):
            line_text, color_type = self.lines[i]
            color = self.text_colors.get(color_type, self.text_colors['info'])
            
            y_pos = text_y + (i - start_line) * self.line_height
            
            # 渲染文本
            if line_text:  # 避免渲染空字符串
                text_surface = self.font.render(line_text, True, color)
                surface.blit(text_surface, (text_x, y_pos))
        
        # 取消裁剪
        surface.set_clip(None)
    
    def _draw_scrollbar(self, surface: pygame.Surface):
        """绘制滚动条"""
        if len(self.lines) <= self.visible_lines:
            return
        
        # 滚动条背景
        scrollbar_x = self.x + self.width - self.scrollbar_width
        scrollbar_rect = pygame.Rect(scrollbar_x, self.y, self.scrollbar_width, self.height)
        pygame.draw.rect(surface, self.scrollbar_color, scrollbar_rect)
        
        # 滚动条手柄
        total_lines = len(self.lines)
        handle_height = max(20, int(self.height * self.visible_lines / total_lines))
        
        max_scroll = total_lines - self.visible_lines
        if max_scroll > 0:
            handle_y_ratio = self.scroll_y / max_scroll
            handle_y = self.y + int((self.height - handle_height) * handle_y_ratio)
        else:
            handle_y = self.y
        
        handle_rect = pygame.Rect(scrollbar_x, handle_y, self.scrollbar_width, handle_height)
        pygame.draw.rect(surface, self.scrollbar_handle_color, handle_rect)
    
    def get_line_count(self) -> int:
        """获取总行数"""
        return len(self.lines)
    
    def get_visible_line_count(self) -> int:
        """获取可见行数"""
        return self.visible_lines
    
    def set_auto_scroll(self, auto_scroll: bool):
        """设置自动滚动"""
        self.auto_scroll = auto_scroll
    
    def set_max_lines(self, max_lines: int):
        """设置最大行数限制"""
        self.max_lines = max_lines
        if len(self.lines) > max_lines:
            self.lines = self.lines[-max_lines:]
            self.scroll_to_bottom()